﻿using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;

namespace CardGameFramework
{
    /// <summary>
    /// Represents a hand of cards in a card game.
    /// </summary>
    public class Hand : IPile
    {
        public event EventHandler<EventArgs> HandBuildCompleted;
        public event EventHandler<PileStateChangedEventArgs> PileStateChanged;

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="deck">The parent deck of cards this hand is playing with.</param>
        /// <param name="minCardCount">Minimum number of cards this hand requires.</param>
        /// <param name="maxCardCount">Maximum number of cards this hand can contain.</param>
        /// <param name="initialCardCount">The initial number of cards this hand will contain.</param>
        public Hand(int minCardCount, int maxCardCount, int initialCardCount)
        {
            Contract.Requires(minCardCount >= 0);
            Contract.Requires(maxCardCount >= 0);
            Contract.Requires(maxCardCount >= minCardCount);
            Contract.Requires(initialCardCount > 0);

            MinCardCount = minCardCount;
            MaxCardCount = maxCardCount;
            PileState = PileStates.Building;
            Cards = new List<Card>();
            InitialCardCount = initialCardCount;
        }

        public int MinCardCount { get; private set; }
        public int MaxCardCount { get; private set; }
        public int InitialCardCount { get; private set; }

        private PileStates _pileState;
        public PileStates PileState
        {
            get { return _pileState; }
            set
            {
                if (_pileState == value) return;

                if (PileStateChanged != null)
                {
                    PileStateChanged(this, 
                                     new PileStateChangedEventArgs()
                                         {
                                             PileState = value, 
                                             PreviousHandState = _pileState
                                         });
                }
                _pileState = value;
            }
        }

        /// <summary>
        /// The list of cards in the hand.
        /// </summary>
        public List<Card> Cards { get; set; }

        /// <summary>
        /// Adds a card to the hand.
        /// </summary>
        /// <param name="card">Card to add to the hand.</param>
        public void AddCard(Card card)
        {
            Contract.Requires(Cards != null);
            Contract.Requires(card != null);
            Contract.Requires(
                (PileState == PileStates.Building && Cards.Count < InitialCardCount)
                || PileState == PileStates.Active && Cards.Count < MaxCardCount);

            Cards.Add(card);

            if (PileState != PileStates.Building || Cards.Count != InitialCardCount) return;

            PileState = PileStates.Active;
            if (HandBuildCompleted != null)
                HandBuildCompleted(this, new EventArgs());
        }

        /// <summary>
        /// Removes a card from the hand.
        /// </summary>
        /// <param name="card"></param>
        public void RemoveCard(Card card)
        {
            Contract.Requires(PileState == PileStates.Active);
            Contract.Requires(Cards != null);
            Contract.Requires(Cards.Contains(card));
            Contract.Requires(Cards.Count > MinCardCount);

            Cards.Remove(card);
        }
    }
}